package com.niiwoo.civet.account.service.local.openAccount2.account;

import com.niiwoo.civet.account.constant.AccountRegisterErrorCode;
import com.niiwoo.civet.account.dao.entity.*;
import com.niiwoo.civet.account.dao.mapper.AccountBaseMapperExt;
import com.niiwoo.civet.account.dao.mapper.BankCardMapperExt;
import com.niiwoo.civet.account.dao.mapper.BankTypeMapperExt;
import com.niiwoo.civet.account.enums.AccountActiveEnum;
import com.niiwoo.civet.account.enums.AccountTypeEnum;
import com.niiwoo.civet.account.service.local.AccountService;
import com.niiwoo.civet.account.service.local.openAccount2.dto.AccountInfo;
import com.niiwoo.civet.base.constant.OrgConstant;
import com.niiwoo.tripod.lanmao.enums.CredentialsTypeEnum;
import com.niiwoo.tripod.lanmao.enums.UserAuthorizationEnum;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class AccountInfoComposite implements ApplicationContextAware {

    @Autowired
    SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    BankTypeMapperExt bankTypeService;
    @Autowired
    private AccountBaseMapperExt accountBaseMapperExt;
    @Autowired
    private AccountService accountService;
    @Autowired
    private BankCardMapperExt bankCardMapperExt;
    private List<AccountExtendOperation> accountExtendOperationList = new ArrayList<>(0);
    private ApplicationContext ctx;

    @PostConstruct
    public void init() {
        Optional.ofNullable(ctx.getBeansOfType(AccountExtendOperation.class)).ifPresent(m -> accountExtendOperationList.addAll(m.values()));
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext.getParent() == null) this.ctx = applicationContext;
    }

    /**
     * 查询唯一账户记录
     *
     * @param userId 用户ID
     * @param userRole 账户角色
     * @param orgId 机构ID
     */
    public AccountBase getAccount(String userId, UserRoleEnum userRole,String orgId) {
        return accountService.getAccount(userId, userRole,orgId);
    }

    /**
     * 保存账户信息, 个人绑卡注册 / 企业绑卡注册（审核通过回调） / 集团账户关联注册 场景
     *
     * @param accountInfo 账户信息
     */
    public boolean save(AccountInfo accountInfo) {
        Set<String> authSet = new HashSet<>(Arrays.asList(accountInfo.getAuthList().split(",")));
        // 账户基础
        AccountBase accountBase = new AccountBase();
        accountBase.setId(snowflakeIdWorker.nextId());
        accountBase.setUserId(accountInfo.getUserId());
        accountBase.setAccountNo(accountInfo.getAccountNo());
        accountBase.setAccountRole(accountInfo.getRole());
        accountBase.setAccountType(accountInfo.getAccountType().getValue());
        accountBase.setCreateTime(new Date());
        accountBase.setImportUserActiva(AccountActiveEnum.ACTIVATED.getValue());
        accountBase.setTender((byte) (authSet.contains(UserAuthorizationEnum.TENDER.name()) ? 1 : 0));
        accountBase.setRepayment((byte) (authSet.contains(UserAuthorizationEnum.REPAYMENT.name()) ? 1 : 0));
        accountBase.setCreditAssignment((byte) (authSet.contains(UserAuthorizationEnum.CREDIT_ASSIGNMENT.name()) ? 1 : 0));
        accountBase.setCompensatory((byte) (authSet.contains(UserAuthorizationEnum.COMPENSATORY.name()) ? 1 : 0));
        accountBase.setWithdraw((byte) (authSet.contains(UserAuthorizationEnum.WITHDRAW.name()) ? 1 : 0));
        accountBase.setRecharge((byte) (authSet.contains(UserAuthorizationEnum.RECHARGE.name()) ? 1 : 0));
        accountBase.setAccountType(accountInfo.getAccountType().getValue());
        accountBase.setOrgId(accountInfo.getOrgId());
        accountBase.setIsShowBill(accountInfo.getIsShowBill());

        // 账户扩展
        AccountPerson accountPerson = new AccountPerson();
        accountPerson.setAccountId(accountBase.getId());
        accountPerson.setAccountNo(accountBase.getAccountNo());
        accountPerson.setUserId(accountBase.getUserId());
        accountPerson.setRealName(accountInfo.getName());
        accountPerson.setIdCard(accountInfo.getIdCardNo());
        accountPerson.setIdCardType(CredentialsTypeEnum.PRC_ID.getValue());
        accountPerson.setOrgId(accountInfo.getOrgId());
        accountPerson.setCreateTime(new Date());
        boolean baseSuccess = accountBaseMapperExt.insertSelective(accountBase) > 0;
        boolean extendSuccess = this.getExtendOperationByType(accountInfo.getAccountType()).save(accountPerson);
        // 银行卡
        boolean bankSuccess = true;
        if (accountInfo.getIsUpdateBankCard()) {
            bankSuccess = this.saveBankCard(accountBase.getId(), accountInfo);
        }
        return baseSuccess && extendSuccess && bankSuccess;
    }

    /**
     * 修改账户信息, 激活账户 / 集团账户关联激活 场景
     *
     * @param accountInfo 账户信息
     */
    public boolean update(AccountInfo accountInfo) {
        AccountBase preBase = accountService.getAccount(accountInfo.getUserId(), UserRoleEnum.enumOf(accountInfo.getRole()),accountInfo.getOrgId());
        // 账户类型从待激活账户中获取
        accountInfo.setAccountType(AccountTypeEnum.of(preBase.getAccountType()));
        Set<String> authSet = StringUtils.isNotBlank(accountInfo.getAuthList()) ? new HashSet<>(Arrays.asList(accountInfo.getAuthList().split(","))) : Collections.emptySet();
        // 账户基础
        AccountBase updateBase = new AccountBase();
        updateBase.setId(preBase.getId());
        updateBase.setImportUserActiva(AccountActiveEnum.ACTIVATED.getValue());
        updateBase.setUpdateTime(new Date());
        if (!authSet.isEmpty()) {
            updateBase.setTender((byte) (authSet.contains(UserAuthorizationEnum.TENDER.name()) ? 1 : 0));
            updateBase.setRepayment((byte) (authSet.contains(UserAuthorizationEnum.REPAYMENT.name()) ? 1 : 0));
            updateBase.setCreditAssignment((byte) (authSet.contains(UserAuthorizationEnum.CREDIT_ASSIGNMENT.name()) ? 1 : 0));
            updateBase.setCompensatory((byte) (authSet.contains(UserAuthorizationEnum.COMPENSATORY.name()) ? 1 : 0));
            updateBase.setWithdraw((byte) (authSet.contains(UserAuthorizationEnum.WITHDRAW.name()) ? 1 : 0));
            updateBase.setRecharge((byte) (authSet.contains(UserAuthorizationEnum.RECHARGE.name()) ? 1 : 0));
            updateBase.setOrgId(accountInfo.getOrgId());
            updateBase.setIsShowBill(accountInfo.getIsShowBill());
        }
        // 账户扩展
        Object extend;
        AccountExtendOperation accountExtendOperation = this.getExtendOperationByType(accountInfo.getAccountType());
        // 个人
        if (accountInfo.getAccountType() == AccountTypeEnum.PERSONAL) {
            AccountPerson accountPerson = new AccountPerson();
            accountPerson.setAccountId(preBase.getId());
            accountPerson.setAuditStatus((byte) 1);
            accountPerson.setRealName(accountInfo.getName());
            accountPerson.setIdCard(accountInfo.getIdCardNo());
            accountPerson.setOrgId(accountInfo.getOrgId());
            accountPerson.setUpdateTime(new Date());
            extend = accountPerson;
            // 企业
        } else {
            AccountCompany company = new AccountCompany();
            company.setAccountId(preBase.getId());
            company.setCompanyName(accountInfo.getName());
            company.setLegalPersonIdCard(accountInfo.getIdCardNo());
            company.setAuditStatus((byte) 1);
            company.setOrgId(accountInfo.getOrgId());
            company.setUpdateTime(new Date());
            extend = company;
            // 企业主动审核没有返回企业名、法人身份证号码和手机号
            boolean isInfoNotEnough = StringUtils.isBlank(accountInfo.getName()) || StringUtils.isBlank(accountInfo.getIdCardNo()) || StringUtils.isBlank(accountInfo.getBankCardMobileNo());
            if (isInfoNotEnough) {
                AccountCompany preCompany = (AccountCompany) accountExtendOperation.getByAccountId(preBase.getId());
                if (StringUtils.isBlank(accountInfo.getName())) {
                    accountInfo.setName(preCompany.getCompanyName());
                }
                if (StringUtils.isBlank(accountInfo.getIdCardNo())) {
                    accountInfo.setIdCardNo(preCompany.getLegalPersonIdCard());
                }
                if (StringUtils.isBlank(accountInfo.getBankCardMobileNo())) {
                    accountInfo.setBankCardMobileNo(preCompany.getContactMobileNo());
                }
            }
        }
        boolean baseSuccess = accountBaseMapperExt.updateByPrimaryKeySelective(updateBase) > 0;
        boolean extendSuccess = accountExtendOperation.update(extend);
        // 银行卡
        boolean bankSuccess = true;
        if (accountInfo.getIsUpdateBankCard()) {
            bankSuccess = this.saveBankCard(updateBase.getId(), accountInfo);
        }
        return baseSuccess && extendSuccess && bankSuccess;
    }

    /**
     * 获取扩展信息操作接口
     *
     * @param accountType 账户类型
     */
    private AccountExtendOperation getExtendOperationByType(AccountTypeEnum accountType) {
        return accountExtendOperationList.stream().filter(op -> op.getType() == accountType).findFirst().orElse(null);
    }

    /**
     * 保存银行卡信息
     */
    private boolean saveBankCard(long baseId, AccountInfo accountInfo) {
        // 获取银行卡
        BankCard preBankCard;
        // 如果是你我金融个人开户，查询集团账户信息；否则查询非集团账户信息
        if(accountInfo.getAccountType() == AccountTypeEnum.PERSONAL && accountInfo.getOrgId().equals(OrgConstant.NIIWOO_ORG_ID)) {
            preBankCard = bankCardMapperExt.selectSimpleUserBankCard(accountInfo.getUserId());
        }else {
            preBankCard = bankCardMapperExt.selectOrgUserBankCard(baseId);
        }

        if (preBankCard != null) {
            // 银行卡存在且银行卡匹配，则不处理
            // 企业用户审核通知没有手机号码、企业名称和法人身份证号码返回
            boolean isNameMatch = preBankCard.getRealName().equals(accountInfo.getName());
            boolean isIdCardMatch = preBankCard.getIdCard().equals(accountInfo.getIdCardNo());
            boolean isBankCardNo = preBankCard.getBankAccountNo().equals(accountInfo.getBankCardNo());
            boolean isBankCardMobileNo = preBankCard.getMobileNo().equals(accountInfo.getBankCardMobileNo());
            // 银行卡四要素匹配，则返回true
            if (isNameMatch && isIdCardMatch && isBankCardNo && isBankCardMobileNo) {
                return true;
                // 银行卡四要素不匹配，则标记删除后新增
            } else {
                BankCard delCard = new BankCard();
                delCard.setId(preBankCard.getId());
                delCard.setDelFlag((byte) 1);
                delCard.setUpdateTime(new Date());
                bankCardMapperExt.updateByPrimaryKeySelective(delCard);
            }
        }
        // 获取银行代码ID
        long bankCardTypeId = Optional.ofNullable(bankTypeService.selectBankTypeByCode(accountInfo.getBankCode())).map(BankType::getId).orElseThrow(() -> new BizException(AccountRegisterErrorCode.UNKNOWN_BANK_TYPE_CODE));
        // 新增银行卡记录
        BankCard bankCard = new BankCard();
        bankCard.setId(snowflakeIdWorker.nextId());
        bankCard.setUserId(accountInfo.getUserId());

        // 如果是个人开户：1、你我金融用户：对私账户--集团账户 2、第三方开户：对私账户--非集团账户
        if(accountInfo.getAccountType() == AccountTypeEnum.PERSONAL) {
            bankCard.setType((byte) 1);
            if(accountInfo.getOrgId().equals(OrgConstant.NIIWOO_ORG_ID)) {
                bankCard.setAccountType(AccountTypeEnum.PERSONAL.getValue());
            }else {
                bankCard.setAccountId(baseId);
                bankCard.setAccountType(AccountTypeEnum.ENTERPRISE.getValue());
            }
        }else {// 如果是企业开户：对公账户--非集团账户
            bankCard.setType((byte) 2);
            bankCard.setAccountId(baseId);
            bankCard.setAccountType(AccountTypeEnum.ENTERPRISE.getValue());
        }

        bankCard.setBankCode(accountInfo.getBankCode());
        bankCard.setBankTypeId(bankCardTypeId);
        bankCard.setBankAccountNo(accountInfo.getBankCardNo());
        bankCard.setMobileNo(StringUtils.defaultIfBlank(accountInfo.getBankCardMobileNo(), preBankCard != null ? preBankCard.getMobileNo() : ""));
        bankCard.setRealName(accountInfo.getName());
        bankCard.setIdCard(accountInfo.getIdCardNo());
        bankCard.setCreateTime(new Date());
        return bankCardMapperExt.insertSelective(bankCard) > 0;
    }

}
